// Copyright (C) 2025 武汉凹语言科技有限公司
// SPDX-License-Identifier: AGPL-3.0-or-later

package loong64

import (
	"unicode"
	"unicode/utf8"
)

func assert(ok bool) {
	if !ok {
		panic("assert failed")
	}
}

// 提取无符号立即数 (unsigned immediate)
func uimm(x uint32, startBit, width uint32) uint32 {
	mask := (uint32(1) << width) - 1
	return (x >> startBit) & mask
}

// 提取有符号立即数 (signed immediate)
func simm(x uint32, startBit, width uint32) int32 {
	val := uimm(x, startBit, width)

	if signBit := uint32(1 << (width - 1)); (val & signBit) != 0 {
		return int32(val) - (int32(1) << width)
	}
	return int32(val)
}

// 把 val 的低 bit 位当作一个有符号数扩展成 int32
func i32SignExtend(val int32, bit uint) int32 {
	// 1. 先左移, 把符号位移到最高位
	// 2. 再算术右移(保持符号), 补全剩余的高位
	return val << (32 - bit) >> (32 - bit)
}

// 忽略大小写
// 下划线和"."视作相同
func strEqualFold(s, t string) bool {
	// ASCII fast path
	i := 0
	for ; i < len(s) && i < len(t); i++ {
		sr := s[i]
		tr := t[i]
		if sr|tr >= utf8.RuneSelf {
			goto hasUnicode
		}

		// Easy case.
		if tr == sr {
			continue
		}

		// Make sr < tr to simplify what follows.
		if tr < sr {
			tr, sr = sr, tr
		}
		// ASCII only, sr/tr must be upper/lower case
		if 'A' <= sr && sr <= 'Z' && tr == sr+'a'-'A' {
			continue
		}
		// '_' 和 '.' 视作相等
		if (sr == '_' && tr == '.') || (sr == '.' && tr == '_') {
			continue
		}
		return false
	}
	// Check if we've exhausted both strings.
	return len(s) == len(t)

hasUnicode:
	s = s[i:]
	t = t[i:]
	for _, sr := range s {
		// If t is exhausted the strings are not equal.
		if len(t) == 0 {
			return false
		}

		// Extract first rune from second string.
		var tr rune
		if t[0] < utf8.RuneSelf {
			tr, t = rune(t[0]), t[1:]
		} else {
			r, size := utf8.DecodeRuneInString(t)
			tr, t = r, t[size:]
		}

		// If they match, keep going; if not, return false.

		// Easy case.
		if tr == sr {
			continue
		}

		// Make sr < tr to simplify what follows.
		if tr < sr {
			tr, sr = sr, tr
		}
		// Fast check for ASCII.
		if tr < utf8.RuneSelf {
			// ASCII only, sr/tr must be upper/lower case
			if 'A' <= sr && sr <= 'Z' && tr == sr+'a'-'A' {
				continue
			}
			// '_' 和 '.' 视作相等
			if (sr == '_' && tr == '.') || (sr == '.' && tr == '_') {
				continue
			}
			return false
		}

		// General case. SimpleFold(x) returns the next equivalent rune > x
		// or wraps around to smaller values.
		r := unicode.SimpleFold(sr)
		for r != sr && r < tr {
			r = unicode.SimpleFold(r)
		}
		if r == tr {
			continue
		}
		return false
	}

	// First string is empty, so check if the second one is also empty.
	return len(t) == 0
}
